/**
 * 下拉刷新/上拉加载更多组件
 * Created By zh25745@ly.com
 * 使用方法：
 * 在目标页按照如下格式引入该文件,路径会有所不同：
 *     gnyPullRefresh = require('./gny-pullRefresh/pullRefresh');
 * 调用时：
 *     var gpr = new gnyPullRefresh(option);初始化
 * 参数说明：
 * option:{
       wrapper: null; iscroll容器id值或者classs名
       cbPullDown: 下拉回调(可选);
       cbPullUp: 上拉回调(可选);
       cbScrollStart: 滚动开始回调(可选);
       cbScrollEnd: 滚动完成回调(可选);
       fixHeader: 固定头部容器(可选);
       fixFooter: 固定底部容器(可选);
 * }
 * 注意:
 *     该组件依赖iscroll-probe.js
 * 更新日志:
 *     2016-07-15 created by zh25745
 *     2016-08-01 updated by zh25745 -- 扩展兼容性，支持filter面板的iscroll
 *     2016-08-05 updated by zh25745 -- 解决不满屏不能滚动的问题
 */
(function(root, factory) {
    if (typeof define === "function" && define.amd) {
        define([], factory);
    } else if (typeof module === "object" && module.exports) {
        module.exports = factory();
    } else {
        root.gnyflight = factory();
    }
}(this, function() {
    function PullUpDown(option) {
        var iScrollConfig = {
            mouseWheel: true,
            preventDefault: false,
            scrollbars: true,
            fadeScrollbars: true,
            probeType: 2,
            bounceTime: 250,
            bounceEasing: "quadratic"
        };
        var wrapper = option.wrapper;
        var wrapperObj = document.querySelector(option.wrapper);
        var cbPullDown = option.cbPullDown;
        var cbPullUp = option.cbPullUp;
        var cbScrollStart = option.cbScrollStart;
        var cbScrollEnd = option.cbScrollEnd;
        var fixHeaderName = option.fixHeader;
        var fixHeader = document.querySelector(option.fixHeader);
        var fixFooter = document.querySelector(option.fixFooter);
        var parent = option.parent;
        var pullThreshold = 5;
        var me = this;
        var offset = {
            scrollStartPos: 0,
            pullDown: 0,
            pullUp: 0
        };
        var elePullDown, elePullUp, eleIcon;
        var MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver;

        var scroll = {
            //初始化异步加载iScroll库
            init: function() {
                scroll.setPosition();
                gnyCommon.asynLoad && gnyCommon.asynLoad("iScrollProbe", scroll.initScroll, {
                    js: "//js.40017.cn/cn/min/??/touch/cn/guoneiyou/lib/iscroll/5.1.2/iscroll-probe.min.js"
                });
            },
            //进行初始化，按需生成上拉下拉提示文案
            initScroll: function() {
                var scrollerObj = wrapperObj.children[0];
                $(wrapperObj).css("position", "absolute");

                if (cbPullDown) {
                    elePullDown = document.createElement("div");
                    elePullDown.className = "pullDown scrolledUp";
                    elePullDown.innerHTML = "<canvas id=pullDownIcon class=pullDownIcon width=36 height=36></canvas><span class=pullDownLabel>下拉进行刷新...</span>";
                    scrollerObj.insertBefore(elePullDown, scrollerObj.firstChild);
                    offset.pullDown = elePullDown.offsetHeight;
                }
                if (cbPullUp) {
                    elePullUp = document.createElement("div");
                    elePullUp.className = "pullUp";
                    elePullUp.innerHTML = "<span class=pullUpIcon></span><span class=pullUpLabel>上拉加载更多...</span>";
                    scrollerObj.appendChild(elePullUp);
                }

                eleIcon = document.querySelector("#pullDownIcon");
                me.myScroll = new IScroll(wrapperObj, iScrollConfig);

                scroll.initEvent();
                me.myScroll.refresh();
            },
            //事件绑定
            initEvent: function() {
                me.myScroll.on("refresh", scroll.refresh);
                me.myScroll.on("scrollStart", scroll.scrollStart);
                me.myScroll.on("scroll", scroll.scroll);
                me.myScroll.on("scrollEnd", scroll.scrollEnd);

                if (fixHeaderName) {
                    scroll.watcher(fixHeaderName, function(e) {
                        if ($(e[0].target).hasClass("iScrollLoneScrollbar")) {
                            return;
                        }
                        // console.log("watched");
                        if (wrapper != fixHeaderName) {
                            scroll.setPosition();
                        }
                        me.myScroll.refresh();
                        me.myScroll.scrollTo(0, 0, 0);
                    });
                }
            },
            //监听header的元素变动，动态设置iscroll容器的高度并进行刷新
            watcher: function(selector, cb) {
                if (!MutationObserver) {
                    return false;
                }
                var mo = new MutationObserver(cb);
                var $dom = document.querySelector(selector);

                var options = {
                    "childList": true,
                    "attributes": true,
                    "subtree": true
                };
                mo.observe($dom, options);
            },
            //设定scroll容器的绝对位置
            setPosition: function() {
                var top = $(fixHeader).height() || 0;
                var bottom = $(fixFooter).height() || 0;
                $(wrapperObj).css("top", top + "px").css("bottom", bottom + "px");
            },
            //iScroll容器刷新，上拉下拉文案归位隐藏
            refresh: function() {
                if (elePullDown) {
                    $(elePullDown).css("margin-top", "-" + elePullDown.height + "px");
                }
                if (elePullDown && $(elePullDown).hasClass("loader")) {
                    $(elePullDown).find(".pullDownLabel").text("下拉进行刷新...");
                    if (this.y >= 0) {
                        scroll.disablePullDown(250, true);
                    } else if (this.y > -offset.pullDown) {
                        elePullDown.style.marginTop = this.y + "px";
                        var animTime = (250 * (offset.pullDown + this.y) / offset.pullDown);
                        this.scrollTo(0, -61, 0);
                        setTimeout(function() {
                            scroll.disablePullDown(animTime, true);
                        }, 0);
                    } else {
                        scroll.disablePullDown(0, true);
                        this.scrollBy(0, offset.pullDown, 0);
                    }
                }
                if (elePullUp && $(elePullUp).hasClass("loader")) {
                    elePullUp.className = "pullUp";
                    $(elePullUp).find(".pullUpLabel").text("上拉加载更多...");
                }

                //解决不满屏不能滚动的问题;
                var h = 50 || $(wrapperObj).height();
                if (Math.abs(this.maxScrollY) < h) {
                    this.maxScrollY = -h;
                }
                // console.log("maxY:" + this.maxScrollY);
            },
            //开始滚动，记录位置点
            scrollStart: function() {
                offset.scrollStartPos = this.y;
                cbScrollStart && cbScrollStart();
            },
            //滚动过程中
            scroll: function() {
                if (elePullDown || elePullUp) {
                    this.y > 0 && renderDownCircle(eleIcon, (this.y) / 60);
                }

                if (elePullDown) {
                    if (this.y > offset.pullDown + pullThreshold && !elePullDown.className.match("flip")) {
                        scroll.enablePullDown("flip");
                        this.scrollBy(0, -offset.pullDown, 0);
                        elePullDown.querySelector(".pullDownLabel").innerHTML = "松手进行刷新...";
                    } else if (this.y < pullThreshold && elePullDown.className.match("flip")) {
                        scroll.disablePullDown(0, false);
                        this.scrollBy(0, offset.pullDown, 0);
                        elePullDown.querySelector(".pullDownLabel").innerHTML = "下拉进行刷新...";
                    }
                }

                if (elePullUp) {
                    if (this.y < (this.maxScrollY - 60) && !elePullUp.className.match("flip")) {
                        elePullUp.className = "pullUp flip";
                        elePullUp.querySelector(".pullUpLabel").innerHTML = "松手获取更多...";
                    } else if (this.y > (this.maxScrollY - 60) && elePullUp.className.match("flip")) {
                        elePullUp.className = "pullUp";
                        elePullUp.querySelector(".pullUpLabel").innerHTML = "上拉加载更多...";
                    }
                }

                //手指滑出滚动边缘，进行归位
                if ((this.y < this.maxScrollY) && (this.pointY < 1)) {
                    this.scrollTo(0, this.maxScrollY, 400);
                    return;
                } else if (this.y > 0 && (this.pointY > window.innerHeight - 1)) {
                    this.scrollTo(0, 0, 400);
                    return;
                }
            },
            //滚动结束，如有回调进行回调
            scrollEnd: function() {
                if (elePullDown || elePullUp) {
                    renderDownCircle(eleIcon, 0);
                }
                if (elePullDown && elePullDown.className.match("flip")) {
                    scroll.enablePullDown("loader");
                    elePullDown.querySelector(".pullDownLabel").innerHTML = "努力加载中...";
                    cbPullDown && cbPullDown(this);
                }
                if ((elePullUp) && (elePullUp.className.match("flip"))) {
                    elePullUp.className = "pullUp loader";
                    elePullUp.querySelector(".pullUpLabel").innerHTML = "努力加载中...";
                    cbPullUp && cbPullUp(this);
                }
                if (offset.scrollStartPos = -1000) {
                    this.hasVerticalScroll = this.options.scrollY && this.maxScrollY < 0;
                }
                cbScrollEnd && cbScrollEnd(this);
                // console.log("scrollEnd y:" + this.y + " maxY:" + this.maxScrollY);
            },
            //显示下拉提示文案
            enablePullDown: function(className) {
                elePullDown.style.transitionDuration = "";
                elePullDown.style.marginTop = "";
                elePullDown.className = "pullDown " + className;
            },
            //隐藏下拉提示文案
            disablePullDown: function(time, refresh) {
                elePullDown.style.transitionDuration = (time > 0 ? time + "ms" : "");
                elePullDown.style.marginTop = "";
                elePullDown.className = "pullDown scrolledUp";
                if (refresh) setTimeout(function() {
                    me.myScroll.refresh();
                }, time + 10);
            }
        };

        function renderDownCircle(ele, eAngleSize) {
            var c = ele;
            var ctx = c.getContext("2d");
            ctx.strokeStyle = '#2fd160';
            ctx.lineWidth = 2;
            ctx.clearRect(0, 0, 36, 36);
            ctx.beginPath();
            ctx.arc(18, 18, 13, 1.5 * Math.PI, (eAngleSize + 1.5) * Math.PI, false);
            ctx.stroke();
        }

        function renderUpCircle(ele, eAngleSize) {
            var c = ele;
            var ctx = c.getContext("2d");
            ctx.strokeStyle = '#2fd160';
            ctx.lineWidth = 2;
            ctx.clearRect(0, 0, 36, 36);
            ctx.beginPath();
            ctx.arc(18, 18, 17, 1.5 * Math.PI, (eAngleSize + 1.5) * Math.PI, false);
            ctx.stroke();
        }

        this.refreshIScroll = function() {
            this.myScroll.refresh();
            this.myScroll.scrollTo(0, 0, 0);
        };

        scroll.init();
    }

    return PullUpDown;
}));